package com.shangxia.lucky.lucky.job;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.shangxia.lucky.common.util.file.ReadTXTUtil;
import com.shangxia.lucky.lucky.ConfigText;
import com.shangxia.lucky.lucky.common.FactoryHead;
import com.shangxia.lucky.lucky.entity.Model;
import com.shangxia.lucky.lucky.writeHandler.MyOverExcelWriteHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.util.*;

/**
 * @author zhouya38158
 * @Package com.shangxia.monomer.business.lucky.job
 * @date 2021/8/26 19:42
 */
@Slf4j
public abstract class MainJob {

    public static List<Integer> ORDER_LIST = new ArrayList<>();
    public static List<List<Integer>> ROW_OVER_LIST = new ArrayList<>();
    public static List<List<Integer>> ROW_OVER_LAST_LIST = new ArrayList<>();
    public static Map<String, Model> ROW_MODELS = new HashMap<>();
    public static Map<String, Model> ROW_LAST_MODELS = new HashMap<>();

    private static ExcelWriter OVER_EXCEL_WRITER;
    private static List<WriteSheet> OVER_SHEETS = new ArrayList<>();

    //统计 最后一层结果
    public static List<Integer> LAST_ROW_RESULT_LIST;

    enum ROW {
        NOW,
        LAST;
    }

    /**
     * 初始化必要参数 输出类
     *
     * @return
     */
    abstract Map<String, Object> initMap();

    abstract void job() throws IOException;

    public void turnOver(Map<String, Object> params, List<List<Integer>> realCodeLists, ConfigText configText) {
        for (int row = 0; row < realCodeLists.size(); row++) {
            params.put("row", row);
            //翻表开始 begin
            log.info("正在计算第 {} 行", 1 + row);
            for (int column = 0; column <= Math.min(row, configText.getBananaOverMaxColumn() - 1); column++) {
                params.put("column", column);
                List<Integer> columnList;
                if (row == 0) {
                    columnList = new ArrayList<>(orderList(configText.bananaCodeLength));
                    columnList.removeAll(realCodeLists.get(0));
                    columnList.addAll(realCodeLists.get(0));
                } else if (column == 0) {
                    ArrayList<Integer> lastRowColumnList = new ArrayList<>(ROW_OVER_LAST_LIST.get(0));
                    lastRowColumnList.removeAll(realCodeLists.get(row));
                    lastRowColumnList.addAll(realCodeLists.get(row));
                    columnList = lastRowColumnList;
                } else {
                    List<Integer> lastColumnList = new ArrayList(ROW_OVER_LIST.get(column - 1));
                    List<Integer> realCodes = new ArrayList();
                    for (int i = 0; i < configText.getBananaSonCodeLength(); i++) {
                        realCodes.add(ROW_OVER_LAST_LIST.get(column - 1)
                                .indexOf(lastColumnList.get(configText.getBananaCodeLength() - configText.getBananaSonCodeLength() + i)) + 1);
                    }
                    if (ROW_OVER_LAST_LIST.size() < column + 2) {
                        columnList = new ArrayList(ORDER_LIST);
                    } else {
                        columnList = new ArrayList(ROW_OVER_LAST_LIST.get(column));
                    }
                    columnList.removeAll(realCodes);
                    columnList.addAll(realCodes);
                }

                ROW_OVER_LIST.add(columnList);
                //翻表开始 end
                //计算匹配情况
                params.put("columnList", columnList);
                doPrivateJob(params, realCodeLists, configText);

            }
            //本层分析计算结束
            //输出本层结果
            exportRowAllResult(configText, params);

            ROW_OVER_LAST_LIST = new ArrayList<>(ROW_OVER_LIST);
            ROW_OVER_LIST.clear();
            ROW_LAST_MODELS = new HashMap<>(ROW_MODELS);
            ROW_MODELS.clear();
        }
        exportLastResultRow();
        exportLastOverRow(null);
    }


    /**
     * 本算法逻辑实现
     *
     * @param params
     * @param realCodeLists
     * @param configText
     */
    public abstract void doPrivateJob(Map<String, Object> params, List<List<Integer>> realCodeLists, ConfigText configText);

    /**
     * 输出本层结果
     *
     * @param configText
     * @param row
     */
    public abstract void exportRowAllResult(ConfigText configText, Map<String, Object> row);

    public abstract void initExportUtil();

    public abstract void exportRowResult(List<Model> resultList, Map<String, Object> params);

    /**
     * 统计最后一行
     *
     * @param resultList
     * @param configText
     */
    public abstract void lastRowData(List<Model> resultList, ConfigText configText);

    /**
     * 读取号码
     *
     * @param fileName
     * @return
     * @throws IOException
     */
    List<List<Integer>> readCode(ConfigText configText, String fileName) throws IOException {
        return ReadTXTUtil.readRealCode(configText.getBananaAbsolutePath(), fileName);
    }

    /**
     * 递增连号
     *
     * @param limit
     * @return
     */
    List<Integer> orderList(Integer limit) {
        if (CollectionUtils.isEmpty(ORDER_LIST)) {
            for (int i = 1; i < limit + 1; i++) {
                ORDER_LIST.add(i);
            }
        }
        return ORDER_LIST;
    }

    /**
     * 输出本层结果
     *  @param rowLastList
     * @param row
     * @param rowList
     * @param configText
     * @param params
     */
    public void exoprtOverResult(List<List<Integer>> rowLastList, int row, List<List<Integer>> rowList, ConfigText configText, Map<String, Object> params) {
        initWriteOver(configText);
        if (CollectionUtils.isEmpty(rowLastList)) {
            return;
        }
        for (int i = 0; i < configText.getBananaOverMaxColumn(); i++) {
            List<List<String>> exportList = new ArrayList<>();
            List<String> list = new ArrayList<>();
            list.add(row + "");
            try {
                rowLastList.get(i).stream().forEach(e -> {
                    list.add("" + e);
                });
                exportList.add(list);
                for (Integer num : rowList.get(i).subList(configText.getBananaCodeLength() - configText.getBananaSonCodeLength(), rowList.get(i).size())) {
                    MyOverExcelWriteHandler.RED_LAST_LIST.add("" + num);
                }
            } catch (IndexOutOfBoundsException e) {
                exportList.add(new ArrayList<>());
            }
            ((ExcelWriter) params.get("OVER_EXCEL_WRITER")).write(exportList, OVER_SHEETS.get(i));
            MyOverExcelWriteHandler.RED_LAST_LIST.clear();
        }
    }

    /**
     * 初始化翻层输出
     *
     * @param configText
     */
    public void initWriteOver(ConfigText configText) {
        if (!configText.getBananaOverExportOpen() || !ObjectUtils.isEmpty(OVER_EXCEL_WRITER) || !ObjectUtils.isEmpty(OVER_SHEETS)) {
            return;
        }
        for (int i = 0; i < configText.getBananaOverMaxColumn(); i++) {
            OVER_SHEETS.add(EasyExcel.writerSheet(i, "第" + (i + 1) + "层")
                    .registerWriteHandler(new MyOverExcelWriteHandler())
                    .head(FactoryHead.head(i, configText.getBananaCodeLength())).build());
        }
        String overFile = configText.getBananaAbsoluteResultPath() + DateFormatUtils.format(new Date(), "yyyy-MM-dd_H-mm-ss_翻层表") + ".xlsx";
        OVER_EXCEL_WRITER = EasyExcel.write(overFile).build();
    }

    public void finishOver() {
        finish();
        if (ObjectUtils.isEmpty(OVER_EXCEL_WRITER) || ObjectUtils.isEmpty(OVER_SHEETS)) {
            return;
        }
        OVER_EXCEL_WRITER.finish();
    }

    public abstract void exportLastResultRow();

    public abstract void exportLastOverRow(List<List<Integer>> rowLastList);

    public abstract void finish();


}
